#define _GNU_SOURCE
#include <stdlib.h>
#include <assert.h>

#include <object.h>
#include <object_table.h>
#include <unittest.h>

/**
 * DESC: Tests the register of a new object.
 *
 * IMP: MEDIUM
 *
 * Use this as an example on how to register your own objects.
 */

typedef struct testobj
{
  object_t obj;
  char data[10];
} testobj_t;


uint16_t testobj_type = 0;

testobj_t *
testobj_new( void )
{
  testobj_t *o = calloc( 1, sizeof(*o) );

  OBJECT_TYPE( o ) = testobj_type;

  return o;
}

void
testobj_free( testobj_t *o )
{
  assert( o != NULL );
  free( o );
}

char *
testobj_str( testobj_t *o )
{
  char *s = NULL;
  int r;

  if ( o == NULL )
    r = asprintf( &s, "TestObj is NULL!" );
  else
    r = asprintf( &s,
		  "TestObj( depth=%d, color=0x%08x, transp=%0.3f, "
		  "data=%p )",
		  OBJECT_DEPTH( o ),
		  COLOR_TO_ARGB( OBJECT_COLOR( o ) ),
		  OBJECT_TRANSP( o ),
		  o->data
		  );
  if ( r < 0 )
    s = NULL;

  return s;
}

void
testobj_draw( testobj_t *o, surface_t *s, unsigned opts )
{
  assert( o != NULL );
  assert( s != NULL );
}


int main( int argc, char *argv[] )
{
  struct object_ops ops = {
    .new = (object_t *(*)(void))testobj_new,
    .free = (void (*)(object_t*))testobj_free,
    .str = (char* (*)(object_t*))testobj_str,
    .draw = (void (*)(object_t*, surface_t *))testobj_draw,
  };

  struct object_table_entry *t;

  atexit(clear_object_table);


  debug_level = 0; /* 1 = warn, 2 = info, 3 = verbose, 4 = debug mode */

  t = add_object_table_entry( "testobj", &ops );

  if ( t != NULL )
    {
      testobj_t *o;
      char *s;

      testobj_type = t->type;

      dbg( "type: %d, name: %s\n", t->type, t->name );

      o = testobj_new();
      s = object_str( OBJECT( o ) );
      dbg( "%s\n", s );
      free( s );

      object_free( OBJECT( o ) );
    }
  else
    {
      err( "Could not add testobj object to table!\n" );
      return -1;
    }

  return 0;
}
